class_name BulletPoisonArrow
extends RigidBody2D

@onready var collision_shape_2d: CollisionShape2D = $HitArea/CollisionShape2D
@onready var hit_area: Area2D = $HitArea
var hit_targets: Array = []
var sender: Node2D = null

@export var max_life: float = 5.0
var attack: float = 0
var critical_rate: float = 0
var critical_bonus: float = 0
var knockback: float = 0
var poison_hit_rate: float = 0
var poison_debuff_duration: float = 0
var poison_damage_per_second: float = 0

@onready var shoot_audio: AudioStreamPlayer2D = $AudioStreamPlayer2D


func _ready() -> void:
	shoot_audio.play()
	
	await get_tree().create_timer(max_life).timeout
	queue_free()
	

func set_start_velocity(velocity: Vector2):
	linear_velocity = velocity


func _physics_process(delta: float) -> void:
	process_rotation(delta)
	process_hit()


func process_rotation(delta):
	if freeze: return
	
	if linear_velocity.length() > 0.1:
		rotation = linear_velocity.angle()


func process_hit():
	if collision_shape_2d.disabled: return
	
	var areas = hit_area.get_overlapping_areas()
	if areas.size() <= 0:
		return
		
	for area in areas:
		var source = area.source as Node2D
		if source is Player: 
			continue
			
		if source not in hit_targets and source.has_method("take_hit"):
			hit_targets.append(source)
			source.take_hit(get_hit_data(), sender)
			
			if source is UnitBase:
				stick_to_target(source)
				add_poison_buff_to_target(source)
				return
				
			queue_free()
			
			
func get_hit_data():
	var hit_data = HitData.new()
	
	var critical_rate = critical_rate
	var is_critical = randf() < critical_rate
	
	hit_data.is_critical = is_critical
	hit_data.attack = attack if not is_critical else attack * (1.0 + critical_bonus)
	hit_data.knockback = knockback
	
	return hit_data
	

func _on_hit_area_body_entered(body: Node2D) -> void:
	collision_shape_2d.disabled = true
	
	linear_velocity = Vector2.ZERO
	angular_velocity = 0
	freeze = true
	freeze_mode = RigidBody2D.FREEZE_MODE_KINEMATIC


func add_poison_buff_to_target(source: Node2D):
	var unit = source as UnitBase
	
	var poison_hit_rate = poison_hit_rate 
	var is_hit = randf() < poison_hit_rate
	if is_hit and not unit.get_buff_by_name("buff_poison"):
		var buff_inst = unit.add_buff("buff_poison", sender)
		
		buff_inst.duration = poison_debuff_duration
		buff_inst.damage_per_second = poison_damage_per_second
		buff_inst.sender = sender
		buff_inst.start_buff()


func stick_to_target(target: Node2D) -> void:
	collision_shape_2d.disabled = true
	
	# 停止物理
	linear_velocity = Vector2.ZERO
	angular_velocity = 0
	freeze = true
	freeze_mode = RigidBody2D.FREEZE_MODE_KINEMATIC
	
	# 先保存当前全局位置与角度
	var pos = global_position
	var rot = global_rotation
	
	# 重新设置父节点
	get_parent().remove_child(self)
	var target_unit = target as UnitBase
	target_unit.stick_parent.add_child(self)
	
	# 保持位置和朝向不变（因为 reparent 会改变本地坐标系）
	global_position = pos
	global_rotation = rot
	
